from serial_rec_send import serial_rec_send
import  threading
import  time
from progress_bar import LineProgress,progress_bar_manager
from os import path
from math import ceil
com="COM2"                 #发送串口的设置
bit=115200                 #设置发送的波特率                         No,这里设置的时候就需要设置超时时间 timeout = 直接把自己设置的超时时间写上即可......
timeout=0.5                #设置读取buffer的超时时间              通过设置buffer大小和timeout=None来控制读入五个字符继续进行，这个是可以的......可以将timeo
FILE_SEND_WAIT_TIME=1      #设置文件传输的过程，即等待 FILE_SEND_WAIT_TIME 的时间进行文件重发
thread_active_time=20      #设置守护线程激活的时间，即守护线程等待 thread_active_time 就将未达到传输次数的线程激活
RE_CONN_COM_TIME=3         #设置串口最大重连次数为 3......
FILE_BLOCK_SIZE=512        #定义文件读取每次读取的文件块大小
class thread_text_com():                                      #实现板子烧录测试的程序，即每次烧录测试时循环测试test_num次
    def __init__(self,temp_args,filename,test_num):
        self.thread_serial=[]
        self.threads=[]
        self.test_num=[]           #为每一个线程单独设置一个烧录模块记录烧录次数
        self.record_num=[]         #记录烧录的次数
        self.record_success=[]     #记录烧录成功的次数
        self.filename=filename
        self.file_hander=[]        #输出文件.log中的函数
        self.re_conn_com_time=[]   #设置重新连接串口的次数
        self.file_block_num=ceil(path.getsize(filename)/FILE_BLOCK_SIZE)#ceil向上取整
        for i in temp_args:
            try:
                progress_bar_manager.put(i, LineProgress(total=self.file_block_num, title=i))
                self.thread_serial.append(serial_rec_send(i,bit,timeout))
                self.test_num.append(test_num)
                self.record_num.append(0)
                self.record_success.append(0)
                self.re_conn_com_time.append(0)
                filename_log='./'+str(i)+'_print.log'
                self.file_hander.append(open(filename_log,'w'))
            except Exception as e:
                print("the com port {} is not opened".format(i))
                a=0
        temp_int_num=0
        for i in self.thread_serial:
            self.threads.append(threading.Thread(target=self.send_reuncle,args=(i,filename,temp_int_num,)))
            temp_int_num+=1

    def send_reuncle(self,temp_i,filename,num_temp_test):
        for i in range(int(self.test_num[num_temp_test])-self.record_num[num_temp_test]):
            self.record_num[num_temp_test]+=1
            try:
                start=time.time()
                temp_i.file_send(filename,self.record_success[num_temp_test])             #我是不是每次发送完end之后板子就reset然后我就可以等待2s之后开始传输
                end = time.time()
            except Exception as e:
                time.sleep(FILE_SEND_WAIT_TIME)
                break
            if temp_i.get_flag()==1:
                #end=time.time()
                str_temp="{} : The file number {} is send sucessfully,cost time:{}. write gone\n"\
                    .format(temp_i.get_port(),self.record_num[num_temp_test],end-start)
                self.file_hander[num_temp_test].write(str(str_temp))
                self.file_hander[num_temp_test].flush()
                self.record_success[num_temp_test]+=1
            else:
                str_temp="{} : The file number {} is send failure. write gone\n".format(temp_i.get_port(),self.record_num[num_temp_test])
                self.file_hander[num_temp_test].write(str(str_temp))
                self.file_hander[num_temp_test].flush()
            time.sleep(FILE_SEND_WAIT_TIME)                   #等待1s再进行传输
        #print("{} : ————文件传输成功次数为-----------{}/{}---------".format(temp_i.get_port(),self.record_success[num_temp_test], self.test_num))
        str_temp="{} : ————文件传输成功次数为-----------{}/{}---------\n".format(temp_i.get_port(),self.record_success[num_temp_test], self.test_num[num_temp_test])
        self.file_hander[num_temp_test].write(str("---------------------------------------------------------------\n"))
        self.file_hander[num_temp_test].write(str(str_temp))
        self.file_hander[num_temp_test].write(str("---------------------------------------------------------------\n"))
        self.file_hander[num_temp_test].flush()

    def begin(self):
        for i in self.threads:
            i.start()
        self.procted_proc=threading.Thread(target=self.protected_proc)
        self.procted_proc.start()

    def protected_proc(self):                          #守护进程防止某些进程意外退出的情况
        while True:
            time.sleep(thread_active_time)                    #每过十秒对线程进行检查
            int_i=int(0);int_set=[]
            for i in self.threads:
                if not i.is_alive():         #线程i存活的话
                    if self.record_num[int_i]<self.test_num[int_i]:
                        int_set.append(int_i)              #就是说只把没有达到传输次数的线程都添加进来即可
                int_i+=1
            for i in int_set:              #更新重启这个线程
                try:
                    self.thread_serial[i]=serial_rec_send(self.thread_serial[i].get_port(),bit,timeout)
                    self.threads[i]=threading.Thread(target=self.send_reuncle,args=(self.thread_serial[i],self.filename,i,))     #应该是尝试重新打开串口的......所以这里需要重新打开这个串口号......
                    self.threads[i].start()
                    self.re_conn_com_time[i]=0       #激活成功的话就将重新连接次数清零
                except Exception as e:               #守护进程尝试重新连接串口，设置链接次数即可
                    self.re_conn_com_time[i]+=1
                    if self.re_conn_com_time[i]>=RE_CONN_COM_TIME:
                        #print("The {} reconnect time is up_MAX, The {} thread is end".format(self.thread_serial[i].get_port(),self.thread_serial[i].get_port()))
                        self.record_num[i]=self.test_num[i]       #直接除掉这个串口重连请求即可......
            int_i=int(0)
            for i in range(len(self.threads)):
                if self.record_num[i]!=self.test_num[i]:
                    int_i+=1
            if int_i==0:   #就是判断线程是否都完成任务了，如果完成任务之后就成功了
                #print("The all thread is over successfully , the process is end.")
                break
        #self.file_hander.close()      #把文件句柄关闭，所有进程结束